#!/bin/bash
set -e

######################## 需要自定义修改的参数 ###################################
# 集群名称
CLICKHOUSE_CLUSTER_NAME="yqtest"
# 数据存放路径
CLICKHOUSE_DATA_DIR=/app/clickhouse
CLICKHOUSE_LOG_DIR=/app/clickhouse_log
# 集群分片节点
CLICKHOUSE_SHARE_IPS="192.168.60.155,192.168.60.156"
#  默认用户 default 的密码，若设置为 '' ，则表示不设置密码
CLICKHOUSE_DEFAULT_USER_PASSWORD='123456'
# CK 常用的两个端口配置
CLICKHOUSE_HTTP_PORT=8123
CLICKHOUSE_TCP_PORT=9000
# 以下端口一般不用更改
CLICKHOUSE_MYSQL_PORT=9004
CLICKHOUSE_POSTGRESQL_PORT=9005
CLICKHOUSE_INTERSERVER_HTTP_PORT=9009
CLICKHOUSE_PROMETHEUS_PORT=9363
# 副本数，默认1，也就是说没有高可用
REPLICA_NUMS=1
# ZK 的配置信息
ZOOKEEPER_IPS="192.168.60.155"
ZOOKEEPER_PORT=2181
# system 的 log 表存留日期
LOG_RETENTION_DAYS=15
# 使用内存,默认获取服务器全量的
CK_MEMORY_ALLLOW_GB=`free -g|grep Mem|awk '{print $2}'`
# 使用CPU核数
CK_CPU_CORES=`cat /proc/cpuinfo| grep "cpu cores"| uniq|awk '{print $4}'`
######################## 需要自定义修改的参数 ###################################


# 以下变量无需修改
CK_IP_ARRAYS=(${CLICKHOUSE_SHARE_IPS//,/ })
ZK_IP_ARRAYS=(${ZOOKEEPER_IPS//,/ })
CHK_PORTS=($CLICKHOUSE_HTTP_PORT $CLICKHOUSE_TCP_PORT $CLICKHOUSE_MYSQL_PORT $CLICKHOUSE_POSTGRESQL_PORT $CLICKHOUSE_INTERSERVER_HTTP_PORT $CLICKHOUSE_PROMETHEUS_PORT)
CK_CONFIG_FILE=/etc/clickhouse-server/config.d/user_server_config.xml

##################################  打印 ######################################
__CEND='\033[0m';
__CBLACK='\033[0;30m';
__CRED='\033[0;31m';
__CGREEN='\033[0;32m';
__CYELLOW='\033[0;33m';
__CBLUE='\033[0;34m';
__CPURPLE='\033[0;35m';
__CCYAN='\033[0;36m';
__CWHITE='\033[0;37m';
__BGREEN='\033[0;42m';
__BYELLOW='\033[0;43m';

print_info(){
    local msg=$1
    echo -e "$(date +"%Y-%m-%d %H:%M:%S") ${__CGREEN}[Info]${__CEND} ${msg} "
}

print_fix(){
    local msg=$1
    echo -e "$(date +"%Y-%m-%d %H:%M:%S") ${__CCYAN}[Fix]${__CEND} ${msg} "
}

print_warning(){
    local msg=$1
    echo -e "$(date +"%Y-%m-%d %H:%M:%S") ${__CYELLOW}[Warning]${__CEND} ${msg}"
}

print_error(){
    local msg=$1
    echo -e "$(date +"%Y-%m-%d %H:%M:%S") ${__CRED}[Error]${__CEND} ${msg}"
}

# 系统内核参数优化
function sys_init() {
    local timestamp=`date +%F-%T`
    mv /etc/sysctl.conf /etc/sysctl.conf.bak-$timestamp
    cat >> /etc/sysctl.conf << EOF
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_max_tw_buckets = 55000
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1100 65535
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 200000
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 2097152
net.core.wmem_max = 2097152
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce=2
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syncookies = 1
vm.swappiness = 0
kernel.sysrq = 1
vm.max_map_count = 262144
fs.inotify.max_user_instances = 8192
EOF
    sysctl -p
    echo "net.netfilter.nf_conntrack_max = 524288" >> /etc/sysctl.conf
    echo -e "root soft nofile 65535\nroot hard nofile 65535\n* soft nofile 65535\n* hard nofile 65535" >> /etc/security/limits.conf
    echo "DefaultLimitNOFILE=65535" >> /etc/systemd/system.conf
    systemctl daemon-reload
}

# 外网连通性检测
function connect_external_check(){
  local TARGET_HOST='223.6.6.6'
  ping -c 1 -W 1 "$TARGET_HOST" > /dev/null
  # 检查 ping 命令的退出状态
  if [ $? -eq 0 ]; then
    #echo "已连接到外部互联网."
    return 0
  else
    #echo "无法连接到外部互联网."
    return 1
  fi
}

# 配置时间同步
function comm_timesync_with_chronyd(){
    local NTP_ADDR0='ntp.tencent.com'
    local NTP_ADDR1='ntp1.tencent.com'
    local NTP_ADDR2='ntp2.tencent.com'
    local NTP_ADDR3='ntp3.tencent.com'

    local CHK_RESULT=$(rpm -qa|grep ntpd|wc -l)
    if [ $CHK_RESULT -gt 0 ];then
        print_warning "当前服务器已安装了NTP，请自行确认是否已配置时间同步！..."
        local CHK_RESULT_STATUS=$(systemctl status ntpd|grep active|wc -l)
        if [ $CHK_RESULT_STATUS -eq 0 ];then
            print_error "ntpd 已安装但未启动，无效可卸载ntpd，脚本会自动安装chrony进行时间同步."
        fi
    else
        local CHK_RESULT_PKG=$(rpm -qa|grep chrony|wc -l)
        if [ $CHK_RESULT_PKG -eq 0 ];then
            print_fix "安装 chrony，并设置时间同步服务器为腾讯时间同步服务器."
            yum -y install chrony
            sed -i 's/^server 0.*.centos.pool.ntp.org.*/server '$NTP_ADDR0' iburst/' /etc/chrony.conf
            sed -i 's/^server 1.*.centos.pool.ntp.org.*/server '$NTP_ADDR1' iburst/' /etc/chrony.conf
            sed -i 's/^server 2.*.centos.pool.ntp.org.*/server '$NTP_ADDR2' iburst/' /etc/chrony.conf
            sed -i 's/^server 3.*.centos.pool.ntp.org.*/server '$NTP_ADDR3' iburst/' /etc/chrony.conf
            systemctl start chronyd
        else
          local CHK_RESULT_STATUS=$(systemctl status chronyd|grep active|wc -l)
          if [ $CHK_RESULT_STATUS -eq 0 ];then
            print_fix "当前服务已安装chrony，但未启动,启动chrony，并设置时间同步服务器为腾讯时间同步服务器[$NTP_ADDR0]."
            sed -i 's/^server 0.*.centos.pool.ntp.org.*/server ntp.tencent.com iburst/' /etc/chrony.conf
            sed -i 's/^server 1.*.centos.pool.ntp.org.*/server ntp1.tencent.com iburst/' /etc/chrony.conf
            sed -i 's/^server 2.*.centos.pool.ntp.org.*/server ntp2.tencent.com iburst/' /etc/chrony.conf
            sed -i 's/^server 3.*.centos.pool.ntp.org.*/server ntp3.tencent.com iburst/' /etc/chrony.conf
            systemctl start chronyd
          else
            print_info "当前服务已安装chrony，且已启动."
          fi  
        fi
    fi 
}

# 系统初始化配置
function check_system_init(){
	print_info "检查系统初始化信息..."
	FIREWALLD_STATUS=`systemctl status firewalld|grep "active (running)"|wc -l`
	print_info "检查防火墙状态..."
	if [ $FIREWALLD_STATUS -gt 0 ];then
	  print_warning "防火墙状态为启用，将执行关闭防火墙..."
	  print_warning "关闭防火墙..."
	  systemctl stop firewalld
	  print_warning "取消防火墙开机自启..."
      systemctl disable firewalld
	fi
	
	print_info "检查 SELINUX 状态..."
	SELINUX_SATUS=`cat /etc/selinux/config |grep "SELINUX=disabled"|wc -l`
	if [ $SELINUX_SATUS -eq 0 ];then
	  print_warning "设置SELINUX为disabled..."
	  setenforce 0
      sed -i s"/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config
	fi

	print_info "检查初始化参数，如 nofile，nproc等..."
    INIT_STATUS=`cat /etc/security/limits.conf|grep soft| grep nofile|grep 65535|grep \*|wc -l`
	if [ $INIT_STATUS -eq 0 ];then
		print_warning "系统尚未进行初始化，进行系统初始化参数设置..."
		sys_init
	fi

  # 检测网络连通性，若连通则使用yum安装，否则使用rpm安装
  print_info "检查配置时间同步..."
  if connect_external_check;then
    comm_timesync_with_chronyd
  else
    print_warning "当前外网不通，请自行配置时间同步!!!"
  fi
}

## 参数预检查
function check_params(){
	print_info "检查基础参数是否已设置..."
	if [ ! "$CLICKHOUSE_CLUSTER_NAME" ] || [ ! "$CK_MEMORY_ALLLOW_GB" ] || [ ! "$CK_CPU_CORES" ] || [ ! "$CLICKHOUSE_DATA_DIR" ] || [ ! "$CLICKHOUSE_SHARE_IPS" ] || [ ! "$CLICKHOUSE_HTTP_PORT" ] || [ ! "$CLICKHOUSE_TCP_PORT" ] || [ ! "$ZOOKEEPER_IPS" ] || [ ! "$ZOOKEEPER_PORT" ] || [ ! "$LOG_RETENTION_DAYS" ];then
    print_error "传入参数不全，请检查"
    exit
  fi

  local ARRAY_NUM=${#CK_IP_ARRAYS[@]}
  if [ $REPLICA_NUMS -gt 1 ];then
    local REMAINDER=$((ARRAY_NUM%REPLICA_NUMS))
    if [ $REMAINDER -gt 0 ];then
      print_error "传入IP参数无法均分为多个分片，请检查！！相关值如下：
      CLICKHOUSE_SHARE_IPS：$CLICKHOUSE_SHARE_IPS
      REPLICA_NUMS：$REPLICA_NUMS"
      exit 1
    fi
  fi
  
}

# 检查端口是否被占用
function comm_check_port_occupied(){
  local port=$1
  local check_value=$(ss -tua | grep -w ${port}|wc -l)
  if [ $check_value -gt 0 ];then
    print_error "端口 [$port] 已被占用,可执行 ss -tua 检查."
    exit 1
  fi
}

# 检查端口是否被占用
function check_port_is_exists(){
  for PORT in ${CHK_PORTS[@]};do
    comm_check_port_occupied $PORT
  done
}

# 检查是否支持安装
function check_env(){
  print_info "检查当前环境是否支持SSE 4.2的命令..."
  ENV_SUPPORTED=`grep -q sse4_2 /proc/cpuinfo && echo "supported" || echo "notsupported"`
  if [[ $ENV_SUPPORTED == "notsupported" ]];then
    print_error "当前环境不支持SSE 4.2命令，无法直接安装ClickHouse..."
       exit 1
  fi
}

# 检查目录
function check_data_isempty(){
  print_info "检查CK数据目录是否为空..."
  if [ -d $CLICKHOUSE_DATA_DIR ];then
    if [ "$(ls -A $CLICKHOUSE_DATA_DIR|grep -v log)" ];then
      print_error "目录$CLICKHOUSE_DATA_DIR 已存在且不为空"
      exit 1
    else
      print_warning "目录$CLICKHOUSE_DATA_DIR 已存在"
    fi
  fi

  if [ -d $CLICKHOUSE_LOG_DIR ];then
    if [ "$(ls -A $CLICKHOUSE_LOG_DIR|grep -v log)" ];then
      print_error "目录$CLICKHOUSE_LOG_DIR 已存在且不为空"
      exit 1
    else
      print_warning "目录$CLICKHOUSE_LOG_DIR 已存在"
    fi
  fi
}

# 检查判断HOSTS是否配置正确
function check_hosts_ip(){
  local HOST=`hostname`
  IPADDR=''
  local IP_IS_EXISTS=0
  for IP in ${CK_IP_ARRAYS[@]};do
    IP_STATUS=`ip -4 a|grep $IP|wc -l`
      if [[ $IP_STATUS -gt 0 ]];then
        IP_IS_EXISTS=1
        IPADDR=$IP
      fi
  done

  if [ $IP_IS_EXISTS -eq 0 ];then
    print_error "传入IP与当前服务器IP不匹配，请检查！"
    exit
  fi

  local IS_SET_HOST=`cat /etc/hosts|grep $HOST|grep $IPADDR|wc -l`
  if [ $IS_SET_HOST -eq 0 ];then
    print_error "/etc/hosts没有正确配置，请检查并配置！"
    exit
  fi
}

function mkdir_path(){
  print_info "检查CK安装路径是否存在：$CLICKHOUSE_DATA_DIR"
  if [ ! -d $CLICKHOUSE_DATA_DIR ];then
    print_info "创建安装路径：$CLICKHOUSE_DATA_DIR "
       mkdir -p $CLICKHOUSE_DATA_DIR
       chown -R clickhouse:clickhouse $CLICKHOUSE_DATA_DIR
     else
       print_info "安装路径已存在：$CLICKHOUSE_DATA_DIR"
  fi

  if [ ! -d $CLICKHOUSE_LOG_DIR ];then
    print_info "创建日志路径：$CLICKHOUSE_LOG_DIR "
       mkdir -p $CLICKHOUSE_LOG_DIR
       chown -R clickhouse:clickhouse $CLICKHOUSE_LOG_DIR
     else
       print_info "日志路径已存在：$CLICKHOUSE_LOG_DIR"
  fi
}

function set_default_password(){
	print_info "配置default用户密码..."
	if [[ "${CLICKHOUSE_DEFAULT_USER_PASSWORD}" = "" ]];then
	  print_warning "用户设置无需配置default密码..."
	else
	  DEFAULT_PASSWORD=`echo -n "${CLICKHOUSE_DEFAULT_USER_PASSWORD}" | sha256sum | tr -d '-'`
	  DEFAULT_PASSWORD_TRIM=`echo $DEFAULT_PASSWORD|grep -o "[^ ]\+\( \+[^ ]\+\)*"`
	  cat > /etc/clickhouse-server/users.d/default-password.xml << EOF
<yandex>
    <users>
        <default>
            <password remove='1' />
            <password_sha256_hex>${DEFAULT_PASSWORD_TRIM}</password_sha256_hex>
        </default>
        <super_admin>
            <password_sha256_hex>${DEFAULT_PASSWORD_TRIM}</password_sha256_hex>
            <profile>default</profile>
            <quota>default</quota>
            <!-- 设置权限管理的能力 -->
            <access_management>1</access_management>
        </super_admin>
    </users>
</yandex>
EOF
	  print_info "配置default用户密码成功"	
	fi
}

# 配置配置文件
function set_server_config(){
  print_info "配置CK server相关的配置信息..."
  cat > ${CK_CONFIG_FILE} <<EOF
<yandex>
    <logger>
        <log replace="replace">${CLICKHOUSE_LOG_DIR}/clickhouse-server.log</log>
        <errorlog replace="replace">${CLICKHOUSE_LOG_DIR}/clickhouse-server.err.log</errorlog>
    </logger>
    <path replace="replace">${CLICKHOUSE_DATA_DIR}/data/</path>
    <tmp_path replace="replace">${CLICKHOUSE_DATA_DIR}/data/tmp/</tmp_path>
    <user_files_path replace="replace">${CLICKHOUSE_DATA_DIR}/data/user_files/</user_files_path>
    <user_directories>
        <local_directory replace="replace">
            <path>${CLICKHOUSE_DATA_DIR}/data/access/</path>
        </local_directory>
    </user_directories>
    <format_schema_path replace="replace">${CLICKHOUSE_DATA_DIR}/data/format_schemas/</format_schema_path>
    <listen_host>::</listen_host>
    <!-- 默认端口 -->
    <http_port replace="replace">$CLICKHOUSE_HTTP_PORT</http_port>
    <tcp_port replace="replace">$CLICKHOUSE_TCP_PORT</tcp_port>
    <mysql_port replace="replace">9004</mysql_port>
    <postgresql_port replace="replace">9005</postgresql_port>
    <!-- 删除表不限制 -->
    <max_table_size_to_drop>0</max_table_size_to_drop>
    <max_partition_size_to_drop>0</max_partition_size_to_drop>
EOF

# 生成集群配置
if [ "$1" == "single" ];then
  set_config_end
else
  set_cluster_info
  set_zookeeper_config
  set_macros_config
  set_config_end
fi
}

# 循环生产 shard
function generate_shard(){
  local SHARD_IPS=$@
  echo "                <shard>" >> ${CK_CONFIG_FILE}
  for REPLICAIP in ${SHARD_IPS[@]};do
    cat >> ${CK_CONFIG_FILE} << EOF
                    <replica>
                        <host>$REPLICAIP</host>
                        <port>${CLICKHOUSE_TCP_PORT}</port>
                        <user>default</user>
                        <!--若没设置密码则为空-->
	    	        <password>${CLICKHOUSE_DEFAULT_USER_PASSWORD}</password>
                    </replica>
EOF
  done
  echo "                </shard>" >> ${CK_CONFIG_FILE}
}

# 配置集群信息
function set_cluster_info(){
echo "
    <remote_servers replace=\"true\">
            <!--自定义集群名称 -->
            <$CLICKHOUSE_CLUSTER_NAME>" >> ${CK_CONFIG_FILE}

local CK_NUMS=${#CK_IP_ARRAYS[@]}
local SHARD_NUMS=$((CK_NUMS/REPLICA_NUMS))
for i in `seq 1 $SHARD_NUMS`;do
    local  START=$(((i-1)*REPLICA_NUMS))
    local  REPS_NUM=${CK_IP_ARRAYS[@]:$START:$REPLICA_NUMS}
    generate_shard $REPS_NUM
done

echo -e "            </$CLICKHOUSE_CLUSTER_NAME>
    </remote_servers>" >> ${CK_CONFIG_FILE}
}

# 配置 zk 信息
function set_zookeeper_config(){
echo -e "
    <!--zookeeper集群相关配置-->
    <zookeeper>" >> ${CK_CONFIG_FILE}
  
  for ZKIP in ${ZK_IP_ARRAYS[@]};do
    echo -e "        <node>
            <host>$ZKIP</host>
            <port>${ZOOKEEPER_PORT}</port>
        </node>" >> ${CK_CONFIG_FILE}
  done

echo "    </zookeeper>" >> ${CK_CONFIG_FILE}
}

# 配置 macros 信息
function set_macros_config(){
  local MACROS_SHARD=`echo ${IPADDR##*.}`
  local CK_NUMS=${#CK_IP_ARRAYS[@]}
  local SHARD_NUMS=$((CK_NUMS/REPLICA_NUMS))

  # 如果IP匹配，则不对IP所属区间，给定所属分片
  for i in "${!CK_IP_ARRAYS[@]}";do
    if [ "${CK_IP_ARRAYS[$i]}" == "$IPADDR" ];then
      for j in `seq 1 $SHARD_NUMS`;do
        local START=$(((j-1)*REPLICA_NUMS))
        local END=$(($j*REPLICA_NUMS))
        if [ $i -ge $START ] && [ $i -lt $END ];then
          local SHARD_INDEX=0$j
          break
        fi
      done
    fi
  done
  
cat >> ${CK_CONFIG_FILE} <<EOF
    <!-- 宏定义，这边需要根据不同的配置更改，xx集群01分片01副本 -->
    <macros>
        <shard>$SHARD_INDEX</shard>
        <replica>$MACROS_SHARD</replica>
    </macros>
EOF
}

function set_config_end(){
cat >> ${CK_CONFIG_FILE} <<EOF
    <!-- 不限制访问来源 -->
    <networks>
        <ip>::/0</ip>
    </networks>
    <!--压缩算法-->
    <compression>
        <case>
            <min_part_size>10000000000</min_part_size>
            <min_part_size_ratio>0.01</min_part_size_ratio>
            <method>lz4</method>
        </case>
    </compression>
        
    <!--设置时区-->
    <timezone>Asia/Shanghai</timezone>
    <!--开放管理用户-->
    <users>
      <default>
        <access_management>1</access_management>
      </default>
    </users>
  
    <!--配置监控信息-->
    <prometheus>
        <endpoint>/metrics</endpoint>
        <port>9363</port>
        <metrics>true</metrics>
        <events>true</events>
        <asynchronous_metrics>true</asynchronous_metrics>
        <status_info>true</status_info>
    </prometheus> 
</yandex>
EOF
}

function set_server_log(){
  print_info "配置服务日志信息与设置TTL..."
  cat > /etc/clickhouse-server/config.d/server_log_config.xml <<EOF
<yandex>
    <query_log replace="replace"> 
        <database>system</database>
        <table>query_log</table>
        <engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_time + INTERVAL ${LOG_RETENTION_DAYS} day SETTINGS ttl_only_drop_parts=1</engine>
        <!-- Interval of flushing data. -->
        <flush_interval_milliseconds>7500</flush_interval_milliseconds>
    </query_log>
    <query_thread_log replace="replace">
        <database>system</database>
        <table>query_thread_log</table>
        <engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_time + INTERVAL ${LOG_RETENTION_DAYS} day SETTINGS ttl_only_drop_parts=1</engine>
        <flush_interval_milliseconds>7500</flush_interval_milliseconds>
    </query_thread_log>
    <metric_log replace="replace">
        <database>system</database>
        <table>metric_log</table>
        <engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_time + INTERVAL ${LOG_RETENTION_DAYS} day SETTINGS ttl_only_drop_parts=1</engine>
        <flush_interval_milliseconds>7500</flush_interval_milliseconds>
        <collect_interval_milliseconds>1000</collect_interval_milliseconds>
    </metric_log>
    <asynchronous_metric_log replace="replace">
        <database>system</database>
        <table>asynchronous_metric_log</table>
        <engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_time + INTERVAL ${LOG_RETENTION_DAYS} day SETTINGS ttl_only_drop_parts=1</engine>
        <flush_interval_milliseconds>7500</flush_interval_milliseconds>
        <collect_interval_milliseconds>1000</collect_interval_milliseconds>
    </asynchronous_metric_log>
    <part_log replace="replace">
        <database>system</database>
        <table>part_log</table>
        <engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_time + INTERVAL ${LOG_RETENTION_DAYS} day SETTINGS ttl_only_drop_parts=1</engine>
        <flush_interval_milliseconds>7500</flush_interval_milliseconds>
    </part_log>
    <trace_log replace="replace">
        <database>system</database>
        <table>trace_log</table>
        <engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_time + INTERVAL ${LOG_RETENTION_DAYS} day SETTINGS ttl_only_drop_parts=1</engine>
        <flush_interval_milliseconds>7500</flush_interval_milliseconds>
    </trace_log>
    <merge_tree replace="1">
      <max_suspicious_broken_parts>20</max_suspicious_broken_parts>
      <!--防止TTL 进程不够删除失败，根据服务器的核数设定，一般设置为相等即可-->
      <max_number_of_merges_with_ttl_in_pool>4</max_number_of_merges_with_ttl_in_pool>
    </merge_tree>
</yandex>
EOF
}

function set_user_config(){
  print_info "配置CK user相关的配置信息..."
  if [[ $CK_MEMORY_ALLLOW_GB -lt 2 ]];then
  	print_warning "内存不足2G，极有可能出现运行异常..."
  elif [[ $CK_MEMORY_ALLLOW_GB -lt 10 ]];then
  	print_warning "内存不足 10G ,内存相对较小，可能导致CK查询时内存不足，或效率低下..."
  fi

  if [[ $CK_CPU_CORES -gt 16 ]];then
  	BACKGROUND_POOL_SIZE=$CK_CPU_CORES
  else
  	BACKGROUND_POOL_SIZE=16
  fi

  MEMORY_SEVENTY=`expr $CK_MEMORY_ALLLOW_GB \* 1024 \* 1024 \* 1024 \* 70 / 100`
  MEMORY_HALF=`expr $CK_MEMORY_ALLLOW_GB \* 1024 \* 1024 \* 1024 \* 50 / 100`
  MEMORY_TWENTY_FIVE=`expr $CK_MEMORY_ALLLOW_GB \* 1024 \* 1024 \* 1024 \* 25 / 100`
  MEMORY_TEN=`expr $CK_MEMORY_ALLLOW_GB \* 1024 \* 1024 \* 1024 \* 10 / 100`
  cat > /etc/clickhouse-server/users.d/user_user_config.xml <<EOF
<yandex>
    <!-- Profiles of settings. -->
    <profiles>
        <!-- Default settings. -->
        <default>
            <use_uncompressed_cache replace="replace">1</use_uncompressed_cache>
            <distributed_directory_monitor_batch_inserts replace="replace">1</distributed_directory_monitor_batch_inserts>
            <send_progress_in_http_headers replace="replace">0</send_progress_in_http_headers>
            <!-- 发送HTTP头X-ClickHouse-Progress的频率不要超过每个指定的间隔。 -->
            <http_headers_progress_interval_ms replace="replace">60000</http_headers_progress_interval_ms>
            <!-- 默认情况下，OPTIMIZE即使它没有做任何事情也会成功返回。此设置可让您区分这些情况并在异常消息中获取原因。 -->
            <optimize_throw_if_noop replace="replace">1</optimize_throw_if_noop>
            <!-- 查询语法树中的最大元素数。如果超过，则抛出异常。 -->
            <max_ast_elements replace="replace">10000000</max_ast_elements>
            <max_expanded_ast_elements replace="replace">10000000</max_expanded_ast_elements>
            <!-- ClickHouse 尝试将hashjoin更改merge为即时加入，以避免内存不足。 -->
            <join_algorithm replace="replace">auto</join_algorithm>
            <!-- 处理单个查询的最大内存使用量。默认10G。当前 -->
            <max_memory_usage replace="replace">$MEMORY_SEVENTY</max_memory_usage>
            <!-- 用于在单个服务器上运行用户查询的最大 RAM 量。-->
            <max_memory_usage_for_user replace="replace">$MEMORY_SEVENTY</max_memory_usage_for_user>
            <!-- 关联时右侧表的最大字节数，默认0，当前设置 1/10,可以适当调大 -->
            <max_bytes_in_join replace="replace">$MEMORY_TEN</max_bytes_in_join>
            <!-- 超出阈值则将数据转储到磁盘进行,一般max_bytes_before_external_group_by设置为max_memory_usage 1/4 -->
            <max_bytes_before_external_group_by replace="replace">$MEMORY_TWENTY_FIVE</max_bytes_before_external_group_by>
            <!-- 超出阈值则将数据转储到磁盘进行,一般设置为max_memory_usage 的 1/2 -->
            <max_bytes_before_external_sort>$MEMORY_HALF</max_bytes_before_external_sort>
            <!-- 小于16则使用默认值(16)，大于则设置为核数的2倍,CPU允许的前提下,设置大一些，提升merge的速度 -->
            <background_pool_size replace="replace">$BACKGROUND_POOL_SIZE</background_pool_size>
        </default>
    </profiles>
</yandex>
EOF
}

function set_config_priv(){
  chown -R clickhouse:clickhouse /etc/clickhouse-server
}

function install_clickhouse(){
  print_info "安装ClickHouse..."
  ls ./soft/clickhouse-*
  if [ $? -gt 0 ];then
    print_error "请查看soft目录是否存在clickhouse的rpm安装包!!!"
    exit 1
  fi
  yum localinstall -y ./soft/clickhouse-*
}

function start_clickhouse(){
  print_info "启动ClickHouse..."
  clickhouse start
}

function uninstall(){
  local IS_RUNNING=$(ps -ef|grep clickhouse-server|grep -v grep|wc -l)
  if [ $IS_RUNNING -gt 0 ];then
    print_info "停止clickhouse..."
    clickhouse stop
    #systemctl stop clickhouse-server.service
  fi
  print_info "卸载ClickHouse安装包..."
  yum remove -y clickhouse*
  if [ -d /etc/clickhouse-server ];then
    print_info "删除配置文件目录 /etc/clickhouse-server"
    rm -rf /etc/clickhouse-server    
  fi
  if [ -d /etc/clickhouse-client ];then
    print_info "删除配置文件目录 /etc/clickhouse-client"
    rm -rf /etc/clickhouse-client    
  fi
  print_info "删除ClickHouse bin 文件 "
  rm -f /usr/bin/clickhouse-disks
  rm -f /usr/bin/clickhouse-git-import
  rm -f /usr/bin/clickhouse-keeper-converter
  print_info "删除ClickHouse doc 文件夹 /usr/share/doc/clickhouse-client /usr/share/doc/clickhouse-common-static  /usr/share/doc/clickhouse-server"
  rm -rf /usr/share/doc/clickhouse-client
  rm -rf /usr/share/doc/clickhouse-common-static
  rm  -rf /usr/share/doc/clickhouse-server
  
  if [ -d $CLICKHOUSE_DATA_DIR ];then
    print_info "删除数据目录 $CLICKHOUSE_DATA_DIR /var/lib/clickhouse"
    rm -rf $CLICKHOUSE_DATA_DIR
    rm -rf /var/lib/clickhouse
  fi
  
  if [ -d $CLICKHOUSE_LOG_DIR ];then
    print_info "删除日志目录 $CLICKHOUSE_LOG_DIR"
    rm -rf $CLICKHOUSE_LOG_DIR
  fi
}

function main(){
  if [ "$1" == "install" ];then
    check_params
    check_port_is_exists
    check_env
    check_system_init
    check_data_isempty
    check_hosts_ip
    install_clickhouse
    mkdir_path
    set_default_password
    set_server_config
    set_server_log
    set_user_config
    set_config_priv
    start_clickhouse
  elif [ "$1" == "uninstall" ];then
    uninstall
  elif [ "$1" == "single" ];then
    check_params
    check_port_is_exists
    check_env
    check_system_init
    check_data_isempty
    check_hosts_ip
    install_clickhouse
    mkdir_path
    set_default_password
    set_server_config 'single'
    set_server_log
    set_user_config
    set_config_priv
    start_clickhouse
  else
    echo -e "
	$0 install 	安装,默认安装分片模式
        $0 single          安装单机版，不会配置集群相关设置
	$0 uninstall 	卸载
"
  fi
}

main $1
